/**
 * Copyright © 2016-2020 The Thingsboard Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.thingsboard.server.service.transport;

import akka.actor.ActorRef;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.iot.manage.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.hsqldb.lib.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.thingsboard.common.util.DonAsynchron;
import org.thingsboard.server.actors.ActorSystemContext;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.msg.cluster.ServerAddress;
import org.thingsboard.server.common.transport.TransportServiceCallback;
import org.thingsboard.server.common.transport.service.AbstractTransportService;
import org.thingsboard.server.config.WebSocketServer;
import org.thingsboard.server.dao.device.ClaimDevicesService;
import org.thingsboard.server.dao.jpa.TApp;
import org.thingsboard.server.dao.jpa.TGateway;
import org.thingsboard.server.dao.jpa.imp.AppRepository;
import org.thingsboard.server.dao.jpa.imp.GatewayRepository;
import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.gen.transport.TransportProtos.ClaimDeviceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.DeviceActorToTransportMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg;
import org.thingsboard.server.gen.transport.TransportProtos.PostTelemetryMsg;
import org.thingsboard.server.gen.transport.TransportProtos.SessionEventMsg;
import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto;
import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToAttributeUpdatesMsg;
import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToRPCMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg;
import org.thingsboard.server.service.cluster.routing.ClusterRoutingService;
import org.thingsboard.server.service.cluster.rpc.ClusterRpcService;
import org.thingsboard.server.service.encoding.DataDecodingEncodingService;
import org.thingsboard.server.service.transport.msg.TransportToDeviceActorMsgWrapper;
import org.thingsboard.server.transport.mqtt.MqttTopics;
import org.thingsboard.server.utils.issue.EventType;
import org.thingsboard.server.utils.issue.IssueGateayMsgBody;
import org.thingsboard.server.utils.issue.IssueReqEventArg;
import org.thingsboard.server.utils.issue.IssueReqMsgBody;
import org.thingsboard.server.utils.msg.MqttReqMsg;
import org.thingsboard.server.utils.msg.MqttReqMsgHeader;
import org.thingsboard.server.utils.msg.MsgType;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;

/**
 * Created by ashvayka on 12.10.18.
 */
@Slf4j
@Service
@ConditionalOnProperty(prefix = "transport", value = "type", havingValue = "local")
public class LocalTransportService extends AbstractTransportService implements RuleEngineTransportService {

    @Autowired
    private ConcurrentHashMap<String,Map> callbackMsgManagement;

    private final Gson gson = new Gson();
    @Autowired
    private TransportApiService transportApiService;

    @Autowired
    private ActorSystemContext actorContext;

    //TODO: completely replace this routing with the Kafka routing by partition ids.
    @Autowired
    private ClusterRoutingService routingService;
    @Autowired
    private ClusterRpcService rpcService;
    @Autowired
    private DataDecodingEncodingService encodingService;
    @Autowired
    private ClaimDevicesService claimDevicesService;

    @Autowired
    private GatewayRepository gatewayRepository;

    @Autowired
    private ProcessService processService;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private ConcurrentHashMap<String, TApp> appManagement;

    @Autowired
    private AppRepository appRepository;

    private Map<String,List<TApp>> maps=new HashMap<>();

    @PostConstruct
    public void init() {
        super.init();
    }

    @PreDestroy
    public void destroy() {
        super.destroy();
    }

    @Override
    public void process(ValidateDeviceTokenRequestMsg msg, TransportServiceCallback<ValidateDeviceCredentialsResponseMsg> callback) {
        DonAsynchron.withCallback(
                transportApiService.handle(TransportApiRequestMsg.newBuilder().setValidateTokenRequestMsg(msg).build()),
                transportApiResponseMsg -> {
                    if (callback != null) {
                        callback.onSuccess(transportApiResponseMsg.getValidateTokenResponseMsg());
                    }
                },
                getThrowableConsumer(callback), transportCallbackExecutor);
    }

    @Override
    public void process(ValidateDeviceX509CertRequestMsg msg, TransportServiceCallback<ValidateDeviceCredentialsResponseMsg> callback) {
        DonAsynchron.withCallback(
                transportApiService.handle(TransportApiRequestMsg.newBuilder().setValidateX509CertRequestMsg(msg).build()),
                transportApiResponseMsg -> {
                    if (callback != null) {
                        callback.onSuccess(transportApiResponseMsg.getValidateTokenResponseMsg());
                    }
                },
                getThrowableConsumer(callback), transportCallbackExecutor);
    }

    @Override
    public void process(GetOrCreateDeviceFromGatewayRequestMsg msg, TransportServiceCallback<GetOrCreateDeviceFromGatewayResponseMsg> callback) {
        DonAsynchron.withCallback(
                transportApiService.handle(TransportApiRequestMsg.newBuilder().setGetOrCreateDeviceRequestMsg(msg).build()),
                transportApiResponseMsg -> {
                    if (callback != null) {
                        callback.onSuccess(transportApiResponseMsg.getGetOrCreateDeviceResponseMsg());
                    }
                },
                getThrowableConsumer(callback), transportCallbackExecutor);
    }


    @Override
    protected void doProcess(SessionInfoProto sessionInfo, SessionEventMsg msg, TransportServiceCallback<Void> callback) {
        forwardToDeviceActor(TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setSessionEvent(msg).build(), callback);
    }

    @Override
    protected void doProcess(SessionInfoProto sessionInfo, PostTelemetryMsg msg, TransportServiceCallback<Void> callback) {
        forwardToDeviceActor(TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setPostTelemetry(msg).build(), callback);
    }

    @Override
    protected void doProcess(SessionInfoProto sessionInfo, PostAttributeMsg msg, TransportServiceCallback<Void> callback) {
        forwardToDeviceActor(TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setPostAttributes(msg).build(), callback);
    }

    @Override
    protected void doProcess(SessionInfoProto sessionInfo, GetAttributeRequestMsg msg, TransportServiceCallback<Void> callback) {
        forwardToDeviceActor(TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setGetAttributes(msg).build(), callback);
    }

    @Override
    public void process(SessionInfoProto sessionInfo, TransportProtos.SubscriptionInfoProto msg, TransportServiceCallback<Void> callback) {
        forwardToDeviceActor(TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setSubscriptionInfo(msg).build(), callback);
    }

    @Override
    public void process(JsonElement json) {
        WebSocketServer.sendInfo(json.toString(),null);
        if(json.isJsonObject()){
            try {
                MqttReqMsg msg = gson.fromJson(json, MqttReqMsg.class);
                //网关上线事件
                if(json.getAsJsonObject().getAsJsonObject("requestBody").get("eventCode").getAsString().equals(EventType.GATEWAY_HEART.eventCodeVal())){
                    addStatus(json.getAsJsonObject().getAsJsonObject("requestHead").get("gatewayId").getAsString(),"online",true);
                    doProcess(msg,MqttTopics.GATEWAY_ATTRIBUTES_TOPIC);
                }
                //边缘代理上线事件
                 else if(null!=json.getAsJsonObject().getAsJsonObject("requestBody").get("deviceCode")&&("".equals(json.getAsJsonObject().getAsJsonObject("requestBody").get("deviceCode").getAsString()))&&json.getAsJsonObject().getAsJsonObject("requestBody").get("eventCode").getAsString().equals(EventType.EVENT_STATUS.eventCodeVal())){
                    addStatus(json.getAsJsonObject().getAsJsonObject("requestHead").get("agentId").getAsString(),"online",false);
                    doAgentProcess(msg,MqttTopics.GATEWAY_ATTRIBUTES_TOPIC);
                }
                //边缘代理设备事件处理
                else if(null!=json.getAsJsonObject().getAsJsonObject("requestBody").get("deviceCode")&&!"".equals(json.getAsJsonObject().getAsJsonObject("requestBody").get("deviceCode").getAsString())&&json.getAsJsonObject().getAsJsonObject("requestBody").get("eventCode").getAsString().equals(EventType.EVENT_STATUS.eventCodeVal())){
                    doDeviceProcess(msg,json.getAsJsonObject());
                }
                //边缘代理下线事件
                else if(json.getAsJsonObject().getAsJsonObject("requestBody").get("eventCode").getAsString().equals(EventType.AGENT_STATUS.eventCodeVal())){
                    addStatus(json.getAsJsonObject().getAsJsonObject("requestHead").get("agentId").getAsString(),"offline",false);
                    doAgentDownProcess(msg,MqttTopics.GATEWAY_ATTRIBUTES_TOPIC);
                }
                //人脸抓拍事件
                else if(json.getAsJsonObject().getAsJsonObject("requestBody").get("eventCode").getAsString().equals(EventType.EVENT_FACE.eventCodeVal())){
                    doDeviceProcess(msg,json.getAsJsonObject());
                }
                //设备告警事件
                else if(json.getAsJsonObject().getAsJsonObject("requestBody").get("eventCode").getAsString().equals(EventType.EVENT_ALARM.eventCodeVal())){
                    doDeviceProcess(msg,json.getAsJsonObject());
                }
                //事件回调
                else if (json.getAsJsonObject().getAsJsonObject("requestBody").get("eventCode").getAsString().equals(EventType.EVENT_RESPONSE.eventCodeVal())){
                    callbackMsgManagement.put(msg.getRequestHead().getMsgId(),gson.fromJson(json,Map.class));
                }

            } catch (RuntimeException e) {
                e.printStackTrace();
                log.info(" Failed to process event msg ");
            }

        }
    }
    //属性处理
    @Override
    public void processAttr(JsonElement jsonElement) {
        WebSocketServer.sendInfo(jsonElement.toString(),null);
        if(jsonElement.isJsonObject()){
            processService.doDeviceAttr(gson.fromJson(jsonElement, MqttReqMsg.class),jsonElement.getAsJsonObject());
        }
    }




    void doDeviceProcess(MqttReqMsg msg,JsonObject jsonObject){
        System.out.println("设备事件处理");
        processService.doDeviceProcess(msg,jsonObject);
    }
    void  doProcess(MqttReqMsg msg,String topic){
        //根据网关获取边缘代理
        List<TGateway> list=gatewayRepository.findAgents(msg.getRequestHead().getGatewayId());
        //mqtt请求头
        MqttReqMsgHeader mqttReqMsgHeader=new MqttReqMsgHeader(MsgType.ARG_ISSUE,msg.getRequestHead().getGatewayId(),null);
        //mqtt请求体
        IssueGateayMsgBody mqttReqMsgBody=new IssueGateayMsgBody(null,EventType.GATEWAY_HEART.eventTypeVal(),EventType.GATEWAY_HEART.eventCodeVal(),null,list);
        MqttReqMsg mqttReqMsg=new MqttReqMsg(mqttReqMsgHeader,mqttReqMsgBody);
        Map map=new HashMap();
        map.put("data",mqttReqMsg);
        map.put("topic",topic);
        //执行过程
        process(msg.getRequestHead().getGatewayId(),null,map);
    }
    public void  doAgentProcess(MqttReqMsg msg, String topic){
        MqttReqMsgHeader mqttReqMsgHeader=new MqttReqMsgHeader(MsgType.ARG_ISSUE,msg.getRequestHead().getGatewayId(),msg.getRequestHead().getAgentId());
//        IssueGateayMsgBody mqttReqMsgBody=new IssueGateayMsgBody(null,EventType.GATEWAY_HEART.eventTypeVal(),EventType.GATEWAY_HEART.eventCodeVal(),processService.getMap(msg.getRequestHead().getAgentId()),null);
//        MqttReqMsg mqttReqMsg=new MqttReqMsg(mqttReqMsgHeader,mqttReqMsgBody);

        Map data=new HashMap();
        data.put("requestHead",mqttReqMsgHeader);
        data.put("requestBody",processService.getMap(msg.getRequestHead().getAgentId()));
        Map map=new HashMap();
        map.put("data",data);
        map.put("topic",topic);
        process(msg.getRequestHead().getGatewayId(),null,map);
    }


    @Override
    public void addStatus(String gatewayCode, String status,boolean flag) {
        //如果是网关下线，组装报文发送给前端
        if(flag&&"offline".equals(status)){
            MqttReqMsgHeader mqttReqMsgHeader=new MqttReqMsgHeader(MsgType.EVENT_REPORT,gatewayCode,null);
            List<IssueReqEventArg> eventArg=new ArrayList<>();
            IssueReqEventArg arg=new IssueReqEventArg();
            arg.setKey("runStatus");
            arg.setType("string");
            arg.setValue(status);
            eventArg.add(arg);
            IssueReqMsgBody mqttReqMsgBody=new IssueReqMsgBody(null,EventType.GATEWAY_HEART.eventTypeVal(),EventType.GATEWAY_HEART.eventCodeVal(),eventArg);
            MqttReqMsg mqttReqMsg=new MqttReqMsg(mqttReqMsgHeader,mqttReqMsgBody);
            System.out.println(JSONObject.toJSON(mqttReqMsg).toString());
            WebSocketServer.sendInfo(JSONObject.toJSON(mqttReqMsg).toString(),null);
        }


        //flag为true表示为网关，一个网关可能对应过个系统
            List<TApp> apps=new ArrayList<>();
            if (null == maps.get(gatewayCode)) {
                if(flag){
                    //通过网关获取所属于的系统
                    apps = appRepository.getAppByGatewayCodes(gatewayCode);
                }else{
                    //通过边缘代理获取所属于的系统
                    apps=appRepository.getAppByGatewayCode(gatewayCode);
                }
                if (!apps.isEmpty()) {
                    maps.put(gatewayCode,apps);
                }
            }
            if(null != maps.get(gatewayCode)&& !maps.get(gatewayCode).isEmpty()){
                for(TApp app:maps.get(gatewayCode)){
                    if(null!=app&&!StringUtil.isEmpty(app.getAppCode())){
                        System.out.println("网关状态:"+app.getAppCode());
                        redisTemplate.opsForValue().set(app.getAppCode() + gatewayCode + ":runStatus" ,status);
                    }
                }
            }
    }

    void  doAgentDownProcess(MqttReqMsg msg,String topic){
        System.out.println("边缘代理下线事件:"+msg.getRequestHead().getAgentId());
    }






    @Override
    protected void doProcess(SessionInfoProto sessionInfo, SubscribeToAttributeUpdatesMsg msg, TransportServiceCallback<Void> callback) {
        forwardToDeviceActor(TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setSubscribeToAttributes(msg).build(), callback);
    }

    @Override
    protected void doProcess(SessionInfoProto sessionInfo, SubscribeToRPCMsg msg, TransportServiceCallback<Void> callback) {
        forwardToDeviceActor(TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setSubscribeToRPC(msg).build(), callback);
    }

    @Override
    protected void doProcess(SessionInfoProto sessionInfo, ToDeviceRpcResponseMsg msg, TransportServiceCallback<Void> callback) {
        forwardToDeviceActor(TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setToDeviceRPCCallResponse(msg).build(), callback);
    }

    @Override
    protected void doProcess(SessionInfoProto sessionInfo, ToServerRpcRequestMsg msg, TransportServiceCallback<Void> callback) {
        forwardToDeviceActor(TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setToServerRPCCallRequest(msg).build(), callback);
    }

    @Override
    protected void registerClaimingInfo(SessionInfoProto sessionInfo, ClaimDeviceMsg msg, TransportServiceCallback<Void> callback) {
        TransportToDeviceActorMsg toDeviceActorMsg = TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setClaimDevice(msg).build();

        TransportToDeviceActorMsgWrapper wrapper = new TransportToDeviceActorMsgWrapper(toDeviceActorMsg);
        Optional<ServerAddress> address = routingService.resolveById(wrapper.getDeviceId());
        if (address.isPresent()) {
            rpcService.tell(encodingService.convertToProtoDataMessage(address.get(), wrapper));
            callback.onSuccess(null);
        } else {
            TenantId tenantId = new TenantId(new UUID(sessionInfo.getTenantIdMSB(), sessionInfo.getTenantIdLSB()));
            DeviceId deviceId = new DeviceId(new UUID(msg.getDeviceIdMSB(), msg.getDeviceIdLSB()));
            DonAsynchron.withCallback(claimDevicesService.registerClaimingInfo(tenantId, deviceId, msg.getSecretKey(), msg.getDurationMs()),
                    callback::onSuccess, callback::onError);
        }
    }

    @Override
    public void process(String nodeId, DeviceActorToTransportMsg msg,Map data) {
        process(nodeId, msg,data, null, null);
    }

    @Override
    public void process(String nodeId, DeviceActorToTransportMsg msg, Map data, Runnable onSuccess, Consumer<Throwable> onFailure) {
        processToTransportMsg(nodeId,msg,data);
        if (onSuccess != null) {
            onSuccess.run();
        }
    }

    private void forwardToDeviceActor(TransportToDeviceActorMsg toDeviceActorMsg, TransportServiceCallback<Void> callback) {
        TransportToDeviceActorMsgWrapper wrapper = new TransportToDeviceActorMsgWrapper(toDeviceActorMsg);
        Optional<ServerAddress> address = routingService.resolveById(wrapper.getDeviceId());
        if (address.isPresent()) {
            rpcService.tell(encodingService.convertToProtoDataMessage(address.get(), wrapper));
        } else {
            actorContext.getAppActor().tell(wrapper, ActorRef.noSender());
        }
        if (callback != null) {
            callback.onSuccess(null);
        }
    }

    private <T> Consumer<Throwable> getThrowableConsumer(TransportServiceCallback<T> callback) {
        return e -> {
            if (callback != null) {
                callback.onError(e);
            }
        };
    }

    public static void main(String[] args) {
        System.out.println("{\"requestHead\":{\"msgId\":\"d1daa88991b44bf4be1d6139df4df0f8\",\"msgType\":\"mtype-arg-issue\",\"timestamp\":1594534017,\"gatewayId\":\"gateway-dky_001\",\"agentId\":\"agent-dky_java_001\"},\"requestBody\":{\"eventType\":\"etype-status\",\"eventCode\":\"gateway-online\",\"requestBody\":{\"agentArg\":[{\"key\":\"transUrl\",\"type\":\"string\",\"value\":\"http://192.168.0.105:8888/service/cli\"},{\"key\":\"transAppName\",\"type\":\"string\",\"value\":\"wiseapp1\"},{\"key\":\"transLoginUser\",\"type\":\"string\",\"value\":\"admin\"},{\"key\":\"transLoginPass\",\"type\":\"string\",\"value\":\"888888\"}],\"modelList\":[{\"modelId\":\"7801a7c05ff7417fa631f87bbfda880f\",\"modelCode\":\"model-camera\",\"modelName\":\"摄像机\",\"modelArg\":{\"propertyList\":[{\"propertyCode\":\"property-real_video_url\",\"configArg\":[{\"key\":\"dataStore\",\"type\":\"String\",\"value\":[\"ram\"]}]},{\"propertyCode\":\"property-record_video_url\",\"configArg\":[{\"key\":\"dataStore\",\"type\":\"String\",\"value\":[\"ram\"]}]},{\"propertyCode\":\"property-courseware_list\",\"configArg\":[{\"key\":\"dataStore\",\"type\":\"String\",\"value\":[\"ram\"]}]},{\"propertyCode\":\"property-record_list\",\"configArg\":[{\"key\":\"dataStore\",\"type\":\"String\",\"value\":[\"ram\"]}]}],\"eventList\":[{\"eventType\":\"event-status\",\"eventCode\":\"event-status\",\"configArg\":[{\"key\":\"dataStore\",\"type\":\"String\",\"value\":[\"ram\",\"redis\"]}]},{\"eventType\":\"etype-alarm\",\"eventCode\":\"event-alarm\",\"configArg\":[{\"key\":\"dataStore\",\"type\":\"String\",\"value\":[\"db\"]}]},{\"eventType\":\"etype-response\",\"eventCode\":\"event-response\",\"configArg\":[]}],\"serviceList\":[{\"serviceCode\":\"service-start_real_video\",\"configArg\":[]},{\"serviceCode\":\"service-stop_real_video\",\"configArg\":[]}]}},{\"modelId\":\"903ed5921aae4b5697e07d0de2eec945\",\"modelCode\":\"model-rps\",\"modelName\":\"录播系统\",\"modelArg\":{\"propertyList\":[{\"propertyCode\":\"property-real_video_url\",\"configArg\":[{\"key\":\"dataStore\",\"type\":\"String\",\"value\":[\"ram\"]}]},{\"propertyCode\":\"property-record_video_url\",\"configArg\":[{\"key\":\"dataStore\",\"type\":\"String\",\"value\":[\"ram\"]}]},{\"propertyCode\":\"property-courseware_list\",\"configArg\":[{\"key\":\"dataStore\",\"type\":\"String\",\"value\":[\"ram\"]}]},{\"propertyCode\":\"property-record_list\",\"configArg\":[{\"key\":\"dataStore\",\"type\":\"String\",\"value\":[\"ram\"]}]}],\"eventList\":[{\"eventType\":\"event-status\",\"eventCode\":\"event-status\",\"configArg\":[{\"key\":\"dataStore\",\"type\":\"String\",\"value\":[\"ram\",\"redis\"]}]},{\"eventType\":\"etype-alarm\",\"eventCode\":\"event-alarm\",\"configArg\":[{\"key\":\"dataStore\",\"type\":\"String\",\"value\":[\"db\"]}]},{\"eventType\":\"etype-response\",\"eventCode\":\"event-response\",\"configArg\":[]}],\"serviceList\":[{\"serviceCode\":\"service-start_real_video\",\"configArg\":[]},{\"serviceCode\":\"service-stop_real_video\",\"configArg\":[]}]}}],\"companyList\":[{\"companyId\":\"57798d44f4564bffa34af72b8b627481\",\"companyCode\":\"company-dh\",\"companyName\":\"大华\"},{\"companyId\":\"7fb9a244725047e38f5e55a3d4973673\",\"companyCode\":\"company-hik\",\"companyName\":\"海康\"},{\"companyId\":\"0a4ce0f335414bccabfce1327c55fa0d\",\"companyCode\":\"company-megvii\",\"companyName\":\"旷视科技\"},{\"companyId\":\"baa2806a5dc447d48ff22bedeb441ca8\",\"companyCode\":\"company-hst\",\"companyName\":\"好视通\"},{\"companyId\":\"b0b31cc46f7943ad99d65d7227e490b\",\"companyCode\":\"company-wx\",\"companyName\":\"无锡录播\",\"companyArg\":\"{\\r\\n \\\"configArg\\\":[\\r\\n {\\r\\n \\\"key\\\":\\\"serviceUrl\\\",\\r\\n \\\"type\\\":\\\"string\\\",\\r\\n \\\"value\\\":\\\"http://127.0.0.1:9090/cgi-bin/encoder.cgi\\\"\\r\\n },\\r\\n {\\r\\n \\\"key\\\":\\\"accessToken\\\",\\r\\n \\\"type\\\":\\\"string\\\",\\r\\n \\\"value\\\":\\\"123456\\\"\\r\\n },\\r\\n {\\r\\n \\\"key\\\":\\\"signature\\\",\\r\\n \\\"type\\\":\\\"string\\\",\\r\\n \\\"value\\\":\\\"123456\\\"\\r\\n },\\r\\n {\\r\\n \\\"key\\\":\\\"sysCompanyName\\\",\\r\\n \\\"type\\\":\\\"string\\\",\\r\\n \\\"value\\\":\\\"dky\\\"\\r\\n },\\r\\n {\\r\\n \\\"key\\\":\\\"loginName\\\",\\r\\n \\\"type\\\":\\\"string\\\",\\r\\n \\\"value\\\":\\\"admin\\\"\\r\\n },\\r\\n {\\r\\n \\\"key\\\":\\\"fileHost\\\",\\r\\n \\\"type\\\":\\\"string\\\",\\r\\n \\\"value\\\":\\\"http://127.0.0.1:9091/\\\"\\r\\n }]\\r\\n}\",\"configArg\":[{\"key\":\"serviceUrl\",\"type\":\"string\",\"value\":\"http://127.0.0.1:9090/cgi-bin/encoder.cgi\"},{\"key\":\"accessToken\",\"type\":\"string\",\"value\":\"123456\"},{\"key\":\"signature\",\"type\":\"string\",\"value\":\"123456\"},{\"key\":\"sysCompanyName\",\"type\":\"string\",\"value\":\"dky\"},{\"key\":\"loginName\",\"type\":\"string\",\"value\":\"admin\"},{\"key\":\"fileHost\",\"type\":\"string\",\"value\":\"http://127.0.0.1:9091/\"}]}],\"deviceList\":[{\"deviceId\":\"29ee19a5f4114c5db007911bc6a6e316\",\"deviceCode\":\"device-dky_8101_rps\",\"deviceName\":\"培训中心8#101录播系统\",\"dtypeCode\":\"dtype-rps\",\"modelCode\":\"model-rps\",\"companyCode\":\"company-wx\",\"gatewayCode\":\"agent-dky_java_001\",\"deviceStatus\":\"dstatus-using\",\"deviceArg\":\"{\\r\\n \\\"configArg\\\":[\\r\\n {\\r\\n \\\"key\\\":\\\"deviceId\\\",\\r\\n \\\"type\\\":\\\"string\\\",\\r\\n \\\"value\\\":\\\"1\\\"\\r\\n },\\r\\n {\\r\\n \\\"key\\\":\\\"Addr\\\",\\r\\n \\\"type\\\":\\\"string\\\",\\r\\n \\\"value\\\":\\\"255\\\"\\r\\n },\\r\\n {\\r\\n \\\"key\\\":\\\"Num\\\",\\r\\n \\\"type\\\":\\\"string\\\",\\r\\n \\\"value\\\":\\\"101\\\"\\r\\n },\\r\\n {\\r\\n \\\"key\\\":\\\"presetSpeed\\\",\\r\\n \\\"type\\\":\\\"string\\\",\\r\\n \\\"value\\\":\\\"50\\\"\\r\\n },\\r\\n {\\r\\n \\\"key\\\":\\\"cameraUrl\\\",\\r\\n \\\"type\\\":\\\"string\\\",\\r\\n \\\"value\\\":\\\"rtmp://202.69.69.180:443/webcast/bshdlive-pc\\\"\\r\\n },\\r\\n {\\r\\n \\\"key\\\":\\\"cameraIp\\\",\\r\\n \\\"type\\\":\\\"string\\\",\\r\\n \\\"value\\\":\\\"127.0.0.1\\\"\\r\\n },\\r\\n {\\r\\n \\\"key\\\":\\\"cameraPort\\\",\\r\\n \\\"type\\\":\\\"string\\\",\\r\\n \\\"value\\\":\\\"9898\\\"\\r\\n }]\\r\\n}\",\"configArg\":[{\"key\":\"deviceId\",\"type\":\"string\",\"value\":\"1\"},{\"key\":\"Addr\",\"type\":\"string\",\"value\":\"255\"},{\"key\":\"Num\",\"type\":\"string\",\"value\":\"101\"},{\"key\":\"presetSpeed\",\"type\":\"string\",\"value\":\"50\"},{\"key\":\"cameraUrl\",\"type\":\"string\",\"value\":\"rtmp://202.69.69.180:443/webcast/bshdlive-pc\"},{\"key\":\"cameraIp\",\"type\":\"string\",\"value\":\"127.0.0.1\"},{\"key\":\"cameraPort\",\"type\":\"string\",\"value\":\"9898\"}]},{\"deviceId\":\"29ee19a5f4114c5db007911bc6a6e317\",\"deviceCode\":\"device-dky_8102_camera\",\"deviceName\":\"培训中心8#101监控摄像头\",\"dtypeCode\":\"dtype-camera\",\"modelCode\":\"model-camera\",\"companyCode\":\"company-hik\",\"gatewayCode\":\"agent-dky_java_001\",\"deviceStatus\":\"dstatus-using\",\"deviceArg\":\"{\\n \\\"configArg\\\":[\\n {\\n \\\"key\\\":\\\"cameraUrl\\\",\\n \\\"type\\\":\\\"string\\\",\\n \\\"value\\\":\\\"rtsp://admin:bwrj123456@192.168.0.221:554/h264/ch1/main/av_stream\\\"\\n },\\n {\\n \\\"key\\\":\\\"playbackUrl\\\",\\n \\\"type\\\":\\\"string\\\",\\n \\\"value\\\":\\\"rtsp://admin:bwrj123456@192.168.0.221:554/h264/Streaming/tracks/101\\\"\\n }]\\n}\\n\",\"configArg\":[{\"key\":\"cameraUrl\",\"type\":\"string\",\"value\":\"rtsp://admin:bwrj123456@192.168.0.221:554/h264/ch1/main/av_stream\"},{\"key\":\"playbackUrl\",\"type\":\"string\",\"value\":\"rtsp://admin:bwrj123456@192.168.0.221:554/h264/Streaming/tracks/101\"}]},{\"deviceId\":\"29ee19a5f4114c5db007911bc6a6e319\",\"deviceCode\":\"device-dky_8104_camera\",\"deviceName\":\"培训中心8#104监控摄像头(人脸抓拍机)\",\"dtypeCode\":\"dtype-camera\",\"modelCode\":\"model-camera\",\"companyCode\":\"company-dh\",\"gatewayCode\":\"agent-dky_java_001\",\"deviceStatus\":\"dstatus-using\",\"deviceArg\":\"{\\r\\n \\\"configArg\\\":[\\r\\n {\\r\\n \\\"key\\\":\\\"cameraUrl\\\",\\r\\n \\\"type\\\":\\\"string\\\",\\r\\n \\\"value\\\":\\\"rtsp://admin:bwrj123456@192.168.0.220:554/cam/realmonitor?channel\\u003d1\\u0026subtype\\u003d1\\\"\\r\\n },\\r\\n {\\r\\n \\\"key\\\":\\\"playbackUrl\\\",\\r\\n \\\"type\\\":\\\"string\\\",\\r\\n \\\"value\\\":\\\"rtsp://admin:bwrj123456@192.168.0.220:554/cam/playback?channel\\u003d1\\u0026subtype\\u003d0\\\"\\r\\n }]\\r\\n}\\r\\n\",\"configArg\":[{\"key\":\"cameraUrl\",\"type\":\"string\",\"value\":\"rtsp://admin:bwrj123456@192.168.0.220:554/cam/realmonitor?channel\\u003d1\\u0026subtype\\u003d1\"},{\"key\":\"playbackUrl\",\"type\":\"string\",\"value\":\"rtsp://admin:bwrj123456@192.168.0.220:554/cam/playback?channel\\u003d1\\u0026subtype\\u003d0\"}]}],\"systemArg\":[{\"type\":\"String\",\"value\":\"172.17.32.100\",\"key\":\"srsIp\"},{\"type\":\"String\",\"value\":\"11936\",\"key\":\"srsRtmpPort\"},{\"type\":\"String\",\"value\":\"8080\",\"key\":\"srsHttpFlvPort\"},{\"type\":\"String\",\"value\":\"http://172.17.32.1:8888\",\"key\":\"fastDFSUrl\"}]}}}".getBytes().length);
    }

}
